#ifndef DATA_STRUCTURE_H
#define DATA_STRUCTURE_H

#include <memory>
#include <map>
#include <vector>
#include <string>
#include <queue>
#include "json/json.h"
#include <list>

// 哨兵营地事件 
#define IT088_ONE "IT088"
#define BA820_ONE "BA820"

#define IT088_1 "IT088_1"
#define IT088_2 "IT088_2"
#define IT088_3 "IT088_3"

#define BA500_1 "BA613"
#define BA500_2 "BA614"
#define BA500_3 "BA615"

// 地图电子围栏事件 
#define CSMAP_1 "BA624"
#define CSMAP_2 "BA625"
#define CSMAP_3 "BA626"
#define CSMAP_4 "BA802"

// hmi topic
#define HMI_TOPIC_BasicObjfusion32 "hmi_interface-HmiInterface.BasicObjfusion32"
#define HMI_TOPIC_BasicMapRoadScene "hmi_interface-HmiInterface.BasicMapRoadScene"
#define HMI_TOPIC_BasicStateFusion "hmi_interface-HmiInterface.BasicStateFusion"

// topic:
// encode_srv-EncodeSrv.EncodeH265-CAM0 //右后 周视
// encode_srv-EncodeSrv.EncodeH265-CAM1 //右前 周视
// encode_srv-EncodeSrv.EncodeH265-CAM2 //左前 周视
// encode_srv-EncodeSrv.EncodeH265-CAM3 //左后 周视
// encode_srv-EncodeSrv.EncodeH265-CAM4 //前 环视
// encode_srv-EncodeSrv.EncodeH265-CAM5 //后 环视
// encode_srv-EncodeSrv.EncodeH265-CAM6 //左 环视
// encode_srv-EncodeSrv.EncodeH265-CAM7 //右 环视
// encode_srv-EncodeSrv.EncodeH265-CAM8 //前视 120
// encode_srv-EncodeSrv.EncodeH265-CAM9 //前视 30
// encode_srv-EncodeSrv.EncodeH265-CAM10 //后视
#define ENCODE_SRV_H265_CAM0 "encode_srv-EncodeSrv.EncodeH265-CAM0"
#define ENCODE_SRV_H265_CAM1 "encode_srv-EncodeSrv.EncodeH265-CAM1"
#define ENCODE_SRV_H265_CAM2 "encode_srv-EncodeSrv.EncodeH265-CAM2"
#define ENCODE_SRV_H265_CAM3 "encode_srv-EncodeSrv.EncodeH265-CAM3"
#define ENCODE_SRV_H265_CAM4 "encode_srv-EncodeSrv.EncodeH265-CAM4"
#define ENCODE_SRV_H265_CAM5 "encode_srv-EncodeSrv.EncodeH265-CAM5"
#define ENCODE_SRV_H265_CAM6 "encode_srv-EncodeSrv.EncodeH265-CAM6"
#define ENCODE_SRV_H265_CAM7 "encode_srv-EncodeSrv.EncodeH265-CAM7"
#define ENCODE_SRV_H265_CAM8 "encode_srv-EncodeSrv.EncodeH265-CAM8"
#define ENCODE_SRV_H265_CAM9 "encode_srv-EncodeSrv.EncodeH265-CAM9"
#define ENCODE_SRV_H265_CAM10 "encode_srv-EncodeSrv.EncodeH265-CAM10"

//脱敏后的topic
#define ENCODE_SRV_DESENS_H265_CAM0 "encode_srv-EncodeSrv.EncodeH265-DesensCAM0"
#define ENCODE_SRV_DESENS_H265_CAM1 "encode_srv-EncodeSrv.EncodeH265-DesensCAM1"
#define ENCODE_SRV_DESENS_H265_CAM2 "encode_srv-EncodeSrv.EncodeH265-DesensCAM2"
#define ENCODE_SRV_DESENS_H265_CAM3 "encode_srv-EncodeSrv.EncodeH265-DesensCAM3"
#define ENCODE_SRV_DESENS_H265_CAM4 "encode_srv-EncodeSrv.EncodeH265-DesensCAM4"
#define ENCODE_SRV_DESENS_H265_CAM5 "encode_srv-EncodeSrv.EncodeH265-DesensCAM5"
#define ENCODE_SRV_DESENS_H265_CAM6 "encode_srv-EncodeSrv.EncodeH265-DesensCAM6"
#define ENCODE_SRV_DESENS_H265_CAM7 "encode_srv-EncodeSrv.EncodeH265-DesensCAM7"
#define ENCODE_SRV_DESENS_H265_CAM8 "encode_srv-EncodeSrv.EncodeH265-DesensCAM8"
#define ENCODE_SRV_DESENS_H265_CAM9 "encode_srv-EncodeSrv.EncodeH265-DesensCAM9"
#define ENCODE_SRV_DESENS_H265_CAM10 "encode_srv-EncodeSrv.EncodeH265-DesensCAM10"

// RPC topic edc->gw
#define PB_BASC_ANDROIDENVIRONMENT_GET_ENVIRONMENT_IN "proxy-Soa.PB_Basc_AndroidEnvironment_Get_Environment_In"

// RPC topic gw->edc
#define PB_BASC_DCENGINEERINGMODEL_RR_SYNCCALIBRATIONFILE_IN "adr-Soa.PB_Basc_DCEngineeringModel_RR_SyncCalibrationFile_In"
#define PB_BASC_DCENGINEERINGMODEL_CNR_STOPTASK_IN "adr-Soa.PB_Basc_DCEngineeringModel_Cnr_StopTask_In"
#define PB_BASC_DCFILEUPLOAD_NTF_UPLOADFILE_IN "adr-Soa.PB_Basc_DCFileUpload_Ntf_UploadFile_In"
#define PB_QUERYFILEPATHINFO_GET_QUERYFILEPATHINFO_IN "adr-Soa.PB_QueryFilePathInfo_Get_QueryFilePathInfo_In"
#define PB_BASC_GETFILEDIRRPC_TRANSFILEDIR_IN "adr-Soa.PB_Basc_getFileDirRPC_transFileDir_In"
#define PB_BASC_VIDEORECORDSERVER_RR_INIT_IN "adr-Soa.PB_Basc_VideoRecordServer_RR_Init_In"
#define PB_BASC_VIDEORECORDSERVER_RR_UINIT_IN "adr-Soa.PB_Basc_VideoRecordServer_RR_Uinit_In"
#define PB_BASC_VIDEORECORDSERVER_RR_REQUESTVIDEOFILE_IN "adr-Soa.PB_Basc_VideoRecordServer_RR_RequestVideoFile_In"

// RPC topic gw->midware
#define PB_BASC_CARFILEUPLOAD_CNR_FILEUPLOAD_C2_IN "adr-Soa.PB_Basc_CarFileUpload_Cnr_FileUpload_C2_In"

#define DAT_FILE_TYPE_MID "1"
#define DAT_FILE_TYPE_VIDEO "2"
#define DAT_FILE_TYPE_JPEG "3"

#define DAT_FILE_TYPE_VIDEO_TUOMIN "4" //脱敏后的视频
#define DAT_FILE_TYPE_JPEG_TUOMIN "5"  //脱敏后的图片

//状态及状态
#define ADC_STATUS_RUNING 0X1   //行车ODD
#define ADC_STATUS_APA 0X2      //泊车ODD
#define ADC_STATUS_OTA 0X3      // OTA模式
#define ADC_STATUS_SHAOBIN 0X4  //哨兵&营地
#define ADC_STATUS_BIAODING 0X5 //标定模式
#define ADC_STATUS_CLOUD 0X6    //离线数据上云
#define ADC_STATUS_MAP 0X6      //众包离线制图
#define ADC_STATUS_DIAG 0X7     //诊断模式

//接收的数据结构
typedef struct ProtoData
{
    //时间戳 调capilot返回的时间戳，代码里用的下面的
    double timestamp;
    // topic
    std::shared_ptr<std::string> topic{nullptr};
    //数据
    std::shared_ptr<std::string> data{nullptr};
    //数据长度
    uint32_t _length;
    //时间戳 getTime()
    uint64_t time;
} ProtoData;

typedef std::multimap<double, ProtoData> PieceProtoData;

//图片采集存储事件发生时，时间发生前5秒 这2帧图片
typedef struct PictureData
{
    double time{0.0};//数据存储时的时间
    ProtoData data;
}PictureData;
typedef struct TopicToPictureData
{
    PictureData pictureDataCacheFirst;
    PictureData pictureDataCacheSecond;
    PictureData pictureDataCacheThird;
}TopicToPictureData;

// proto有效时长
typedef struct ProtoValidTime
{
    double beforeTime{0.0};
    double afterTime{0.0};
} ProtoValidTime;

typedef enum CondRuleCompareType
{
    //不比较直接true
    CRCT_NONE = 0,
    //大于
    CRCT_BIGER_THAN = 1,
    //小于
    CRCT_SMALLER_THAN = 2,
    //等于
    CRCT_EQUAL_THAN = 3,
    //不等于
    CRCT_NOT_EQUAL = 4,
    //大于等于
    CRCT_BIGER_EQUAL_THAN = 5,
    //小于等于
    CRCT_SMALLER_EQUAL_THAN = 6,
    //跳变 eg: 0->1
    CRCT_CHANGE = 7,
    //跳变 不等于的跳变 eg: 非0 -> 1
    CRCT_CHANGE_NOTNOE2ONE = 8,
    //跳变 不等于的跳变 eg: 1 -> 非0
    CRCT_CHANGE_ONE2NOTNOE = 9
} CondRuleCompareType;

//父条件与子条件关系
typedef enum CondRuleType
{
    //与
    CRT_AND = 0,
    //或
    CRT_OR,
} CondRuleType;

//条件状态
typedef enum TriggerStatus
{
    TS_NONE = 0,
    TS_START,
    TS_END,
} TriggerStatus;

//==================================================proto条件引擎
typedef struct ProtoCondRuleSignalInfo_t
{
    // topic名
    std::string topic;
    // proto message名,与topic一一对应，不用配置proto文件，proto文件默认全部加载
    // 这里msg包括proto文件里的package
    std::string protoMsg;
    //信号名,兼容嵌套message，message成员member
    std::queue<std::string> name;
    //比较运算,//比较值，这里用double兼容其他类型，int和bool
    CondRuleCompareType opera;
    //值
    Json::Value constValue;
    //值类型
    std::string valueType;
    //值,跳变
    std::vector<Json::Value> changeVec;
    //条件表达式中有跳变的，保存之前的值
    Json::Value changeOldValue;
    //唯一标识
    std::string id;
    //信号英文名 给edc发快照里才配的有
    std::string signalName;
    // 持续时间要求(ms)
    uint64_t time = 0;
    // 首次满足触发条件时的时间戳(存在time字段时生效)
    uint64_t beforeTimeStamp = 0;
} ProtoCondRuleSignalInfo_t;

/**
 * \brief proto条件采集配置，单个事件
 **/
typedef struct ProtoCondRule_t
{
    //当前层表达式逻辑运算
    CondRuleType expressRuleType;
    //当前层表达式，单个元素判断规则
    std::vector<ProtoCondRuleSignalInfo_t> expressRule;
    //条件出发次数,0,1指触发一次就行,预计值
    int triggerTimesExpect{0};
    //出发实际值
    int triggerTimesReal{0};
    //当前层与子层的关系
    CondRuleType childRuleType;
    //子层条件细则，递归
    std::shared_ptr<ProtoCondRule_t> childRule{nullptr};
} ProtoCondRule_t;

/**
 * \brief proto条件采集配置，单个事件
 **/
typedef struct ProtoCondInfo_t
{
    //条件采集专用----------------------------------
    // mqtt传输服务名
    std::string serviceKey = "";
    // mqtt传输方法
    std::string method = "";
    //传输等级
    int level = 0;
    //事件事件名称ID
    std::string eventName = "";
    //事件规则，条件开始
    std::shared_ptr<ProtoCondRule_t> rules{nullptr};
    //事件规则，条件结束
    std::shared_ptr<ProtoCondRule_t> rulesEnd{nullptr};
    //需要采集数据
    std::vector<std::string> collectData;
    //前多少毫秒
    double beforeTime;
    //后多少毫秒
    double laterTime;

    //此事件上次触发时间
    double trigLaterTime = 0.0;
    //此事件配置的事件触发间隔
    double limitTime = 300000;//5min间隔 zjs_todo;会增加到2倍，10min?

    //特殊事件关联的topic（判断条件代码写死，不走条件引擎）
    std::vector<std::string> specialRelatedTopic;
    

    TriggerStatus status{TS_NONE};//瞬时事件为TS_NONE；过程事件TS_NONE-》TS_START -》 TS_END
} ProtoCondInfo_t;

//==================================================proto条件引擎

//触发的事件文件，来自其他控制器
struct TrigerFile
{
    //控制器名称
    std::string controllerCode;
    //文件名
    std::string fileName;
};

// typedef struct SentryParam
// {
//   uint8_t triggerType;
//   uint16_t beforeTime;
//   uint32_t backTime;
//   uint8_t camera;
//   uint64_t taskId;
// } SentryParam;


//触发的事件信息详情 用于给data_catch采集数据用(事件触发后，用这个结构给m_eventPool进行后续处理，定时遍历采集数据用)
typedef struct TriggerEventInfo
{
    //需要采集的信号/topic
    std::vector<std::string> collectDatas;
    //触发时间
    double triggerTime{0.0};
    //触发时的开机时间,使用框架接口获取
    double triggerStartTime{0.0};
    //记录时间
    uint64_t recordTime{0};
    //事件ID
    std::string eventName{""};
    //事件前多少秒
    double beforeTime{0.0};
    //事件后多少秒
    double laterTime{0.0};
    //同一个事件，来自其他控制器
    std::vector<TrigerFile> otherSysFile;
    //传输等级
    int level{6};
    //任务ID
    uint64_t taskId{0};
    //哨塔触发类型
    uint8_t triggerType{0};
    //状态
    TriggerStatus status{TS_NONE};
    uint32_t timeout{0};    
} TriggerEventInfo;

typedef struct SocketDataHeader
{
    uint8_t camera{0};               //哪路摄像头
    uint64_t startFrameTimeStamp{0}; //该文件首帧时间戳
    uint64_t endFrameTimeStamp{0};   //该文件尾帧时间戳
    uint64_t fileSize{0};            //文件大小
} SocketDataHeader;

typedef struct SocketData
{
    SocketDataHeader header;
    std::vector<std::string> data; // data
} SocketData;

// 文件上传状态类型
typedef enum FileUpLoadStatus_t
{
    // 值未初始化
    NO_INITIALIZED = 0,
    // 上传文件成功
    UPLOAD_FILE_SUCCESS = 1,
    // 文件开始上传
    FILE_START_UPLOAD = 2,
    // 开始发送文件上传结果
    SEND_FILE_UPLOAD_RESULT = 3,
    // 下发指令解析失败
    INSTRUCT_PARSE_FAIL = 4,
    // 下发指令taskID为空
    INSTRUCT_TASKID_EMPTY = 5,
    // 下发指令控制器名称错误
    INSTRUCT_CONTROLLER_NAME_ERROR = 6,
    // 下发指令文件名为空
    INSTRUCT_FILE_NAME_EMPTY = 7,
    // 下发指令文件路径为空
    INSTRUCT_FILE_PATH_EMPTY = 8,
    // 获取token失败
    GET_TOKEN_ERROR = 9,
    // 车端TUID文件不存在
    TUID_NOT_EXIST = 10,
    // 车端证书公钥不存在
    ROOTCA_CER_NOT_EXIST = 11,
    // 车端证书私钥cert不存在
    CLIENT_CER_NOT_EXIST = 12,
    // 车端证书私钥key不存在
    PRIVATE_KEY_NOT_EXIST = 13,
    // 文件不存在
    FILE_NOT_EXIST = 14,
    // 获取文件上传链接失败
    GET_FILE_UPLOAD_LINK_ERROR = 15,
    // 上传链接响应数据解析失败
    FILE_UPLOAD_LINK_RESPONSE_DATA_PARSE_FAIL = 16,
    // 文件上传链接为空
    FILE_UPLOAD_LINK_EMPTY = 17,
    // 文件上传响应数据解析失败
    FILE_UPLOAD_RESPONSE_DATA_PARSE_FAIL = 18,
    // 请求发送文件上传结果失败
    SEND_FILE_UPLOAD_RESULT_REQUEST_FAIL = 19,
    // 文件上传网络超时
    FILE_UPLOAD_TIMEOUT_WAS_REACHED = 20,
    // 文件为空
    FILE_SIZE_EQUAL_ZERO = 21,
    // 文件大小超过限制
    FILE_SIZE_OVER_LIMIT = 22,
} FileUpLoadStatus_t;

// 文件上传参数
typedef struct FileUploadParam
{
    std::string taskId; // 文件上传 任务ID
    std::string fileName; // 文件名
    std::string filePath; // 文件路径
    std::string eventCode; // 此文件对应的事件编号
    std::string businessType;//文件上传的业务类型
}FileUploadParam;

#endif // DATA_STRUCTURE_H
